home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / MacSource / AEUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-14  |  15.2 KB  |  548 lines  |  [TEXT/CWIE]

  1. /*==============================================================================
  2. Project:    POV
  3.  
  4. Version:    3
  5.  
  6. File:        aeUtils.c
  7.  
  8. Description:
  9.     AppleEvent utils & required aevt handlers.
  10. ------------------------------------------------------------------------------
  11. Author:
  12.     Eduard [esp] Schwan
  13. ------------------------------------------------------------------------------
  14.     from Persistence of Vision(tm) Ray Tracer
  15.     Copyright 1996 Persistence of Vision Team
  16. ------------------------------------------------------------------------------
  17.     NOTICE: This source code file is provided so that users may experiment
  18.     with enhancements to POV-Ray and to port the software to platforms other 
  19.     than those supported by the POV-Ray Team.  There are strict rules under
  20.     which you are permitted to use this file.  The rules are in the file
  21.     named POVLEGAL.DOC which should be distributed with this file. If 
  22.     POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  23.     Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  24.     Forum.  The latest version of POV-Ray may be found there as well.
  25.  
  26.     This program is based on the popular DKB raytracer version 2.12.
  27.     DKBTrace was originally written by David K. Buck.
  28.     DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  29. ------------------------------------------------------------------------------
  30. Change History:
  31.     960120    [esp]    Added core-handling skeleton
  32. ==============================================================================*/
  33.  
  34. #define AEUTILS_C
  35.  
  36. #include "AEUtils.h"
  37.  
  38. #include <AppleEvents.h>
  39. #include <AERegistry.h>
  40. #include <CodeFragments.h> // kUnresolvedSymbolAddress
  41.  
  42. #include "POVMac.h"
  43. #include "UtilLib.h"
  44. #include "StdFolder.h"
  45. #include "FileQueue.h"
  46. #include "AppPrefs.h"
  47. #include "Texteditor.h"
  48.  
  49. #include "AEObjects.h"
  50. #include "Gestalt.h"
  51.  
  52. #include "aeTok.h"
  53. #include "aeAppHdlr.h"
  54.  
  55.  
  56. // ---------------------------------------------------------------------
  57. Boolean    gAppleScriptAvail=false;
  58.  
  59. // ---------------------------------------------------------------------
  60. // utility to extract a short integer from an AEDesc
  61. #pragma segment Main
  62.  
  63. OSErr ExtractShortFromAEDesc(    AEDesc    *theDesc,
  64.                                 short    *theShortPtr)
  65.     {
  66.     OSErr anError = noErr;
  67.     AEDesc tempDesc;
  68.     
  69.     if (theDesc->descriptorType == typeShortInteger)
  70.         {
  71.         
  72.         *theShortPtr = **((short **)theDesc->dataHandle);
  73.         }
  74.     else
  75.         {
  76.         /* if it wasn't a short to begin with, try and coerce it into a short */
  77.         anError = AECoerceDesc(theDesc, typeShortInteger, &tempDesc);
  78.         if (!anError)
  79.             {
  80.             /* it coerced.  grab it */
  81.             *theShortPtr = **((short **)tempDesc.dataHandle);
  82.             AEDisposeDesc(&tempDesc);
  83.             }
  84.         }
  85.     return anError;
  86.     } // ExtractShortFromAEDesc
  87.  
  88.  
  89. // ---------------------------------------------------------------------
  90. // Send a System Seven Shutdown AppleEvent to the Finder to shut us all down
  91. void SendAEShutdown(void)
  92. {
  93.     OSErr        myErr;
  94.     OSType        theSignature;
  95.     AppleEvent    myAEvt, myReturnEvt;
  96.     AEAddressDesc    myServerAddress;
  97.  
  98.     theSignature = 'MACS'; // Finder signature.. of course!?
  99.     myErr = AECreateDesc(typeApplSignature, (Ptr)&theSignature, 4, &myServerAddress);
  100.     if (!myErr)
  101.         myErr = AECreateAppleEvent(kAEFinderEvents,            // Event Class
  102.                                     kAEShutDown,            // Event ID
  103.                                     &myServerAddress,        // Target Adr
  104.                                     kAutoGenerateReturnID,    // Return aevt ID
  105.                                     kAnyTransactionID,        // Trans ID
  106.                                     &myAEvt);                // fill me in
  107.     if (!myErr)
  108.         myErr = AESend(&myAEvt,
  109.                         &myReturnEvt,
  110.                         kAENoReply,                // send mode
  111.                         kAENormalPriority,        // send priority
  112.                         kNoTimeOut,                // N timeout ticks
  113.                         NULL,                    // idleProcPtr
  114.                         NULL);                    // EventFilterProcPtr
  115.     /* may as well clean up before we die :-) */
  116.     if (!myErr)
  117.         myErr = AEDisposeDesc(&myServerAddress);
  118. } // SendAEShutdown
  119.  
  120.  
  121. // ---------------------------------------------------------------------
  122. // Returns TRUE if all required AE parms were extracted OK
  123. #pragma segment Main
  124. OSErr GotRequiredAEParams(AppleEvent    *theAppleEvent)
  125. {
  126.     DescType    typeCode;
  127.     Size        actualSize;
  128.     OSErr        err;
  129.  
  130.     err = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
  131.                             &typeCode, NULL, 0, &actualSize);    /* NULL ok here; need only function result */
  132.     if (err == errAEDescNotFound)
  133.         // we got all the required params: all is ok
  134.         return noErr;
  135.     else if (err == noErr)
  136.         // found one left behind: error!
  137.         return errAEEventNotHandled;
  138.     else
  139.         // some other oddity
  140.         return err;
  141. } // GotRequiredAEParams
  142.  
  143.  
  144.  
  145. // ---------------------------------------------------------------------
  146. // AE Handler - Oapp - If app run with no documents
  147. #pragma segment Main
  148. static pascal OSErr HandleAEOapp(AEDescList *aevt, AEDescList *reply, long refCon)
  149. {
  150. #pragma unused (reply,refCon)
  151.     OSErr    anError;
  152.  
  153.     /* We don't normally expect any parms, but check in case the client requires any */
  154.     anError = GotRequiredAEParams(aevt);
  155.  
  156.     // if user hasn't already opened a window, open a new untitled window
  157.     if (!anError && (gSrcWind_VRefNum == 0))
  158.         DoFile_New();
  159.  
  160.     return anError;
  161. } // HandleAEOApp
  162.  
  163.  
  164. // ---------------------------------------------------------------------
  165. static OSErr DoAEOpenFile(    FSSpecPtr    theFSSpec,
  166.                             long        index,
  167.                             long        numFiles,
  168.                             Boolean        forPrinting)
  169. {
  170.     OSErr        anError = noErr;
  171.     FInfo        theFileInfo;
  172.     char        theFname[32];
  173.  
  174.     // C version of filename
  175.     BlockMove(theFSSpec->name, theFname, theFSSpec->name[0]+1);
  176.     p2cstr((StringPtr)theFname);
  177.  
  178.     if ((**gDefltFilePrefs_h).progress >= eProgDebug)
  179.     {
  180.         printf("-d ODOC='%s'\n", theFname);
  181.     }
  182.  
  183.     // better be a text file..
  184.     // Note: We're in an AE Handler, so guaranteed to be System 7, so ok to call:
  185.     FSpGetFInfo(theFSSpec, &theFileInfo);
  186.     if (theFileInfo.fdType != 'TEXT')
  187.     {
  188.         (void)DisplayModalDialog(kdlog_CantOpenNonText,
  189.                         ok, 0, theFname, 0, ewcDoCentering, eSameAsPassedWindow);
  190.         anError = 1;
  191.     }
  192.  
  193.     /* Open the File here */
  194.     if (!anError)
  195.     {
  196.         // Use this file to set anchor for any future SFGetFile opens...
  197.         // in other words, if you drop one or more files onto POV-Ray, then
  198.         // the next time you do a File-Open, the standard file dialog will
  199.         // open at the directory of your dropped file, not the app directory.
  200.         // (You're welcome Anton! [esp] :-)
  201.         if (index == 1)
  202.             SF_SetSFCurrent(theFSSpec);
  203.  
  204.         if ((**gDefltFilePrefs_h).progress >= eProgDebug)
  205.         {
  206.             printf("-d  NumFiles=%d,  DoingBatch=%d,  DoingRender=%d\n",
  207.                     (int)numFiles, gDoingBatchODOCs, gDoingRender);
  208.         }
  209.  
  210.         // already queued some, or
  211.         // we're "printing" (which means auto-render)
  212.         // so queue these too
  213.         if (gDoingBatchODOCs || forPrinting)
  214.         {
  215.             FileQ_Put(theFSSpec);
  216.         }
  217.         else
  218.         {
  219.             // Don't open it if a file is already open and dirty (unsaved)
  220.             if (gSrcWind_dirty)
  221.             {
  222.                 (void)DisplayModalDialog(kdlog_CantOpenOverDirty,
  223.                                 ok, 0, NULL, 0, ewcDoCentering, eSameAsPassedWindow);
  224.                 anError = 1; // no more files..
  225.             }
  226.             else
  227.             {    // ok to open
  228.                 if ((numFiles == 1) && !gDoingRender)
  229.                 {
  230.                     // Simple case, just one file to open, just open it and wait
  231.                     OpenTextFile(theFSSpec->name, theFSSpec->vRefNum, theFSSpec->parID, true/*UseDirID*/);
  232.                 }
  233.                 else
  234.                 {
  235.                     // mult. files dropped, or already rendering one.
  236.                     // put each file in a queue for later batch processing
  237.                     FileQ_Put(theFSSpec);
  238.  
  239.                     // This is a sly way to tell DoRendering() to save the current
  240.                     // file being rendered automatically, before opening the next
  241.                     // file in the queue.
  242.                     if (gDoingRender)
  243.                         gDoingBatchODOCs = true;
  244.                 }
  245.             }    // else ok to add
  246.         }
  247.     }    // if !error
  248.     return anError;
  249. }
  250.  
  251.  
  252. // ---------------------------------------------------------------------
  253. // common ODOC/PDOC AE Handler
  254. #pragma segment Main
  255. static OSErr HandleAECommonOPDox(    AEDescList        *aevt,
  256.                                     AEDescList        *reply,
  257.                                     long            refCon,
  258.                                     Boolean            forPrinting)
  259. {
  260. #pragma unused(reply,refCon)
  261.     OSErr        anError = noErr;
  262.     AEDesc        fileListDesc;
  263.     DescType    actualType;
  264.     long        actualSize;
  265.     AEKeyword    actualKeyword;
  266.     FSSpec        oneFSSpec;
  267.     long        numFiles;
  268.     long        index;
  269.                         
  270.     //
  271.     // The "odoc" and "pdoc" messages contain a list of aliases as the direct paramater.
  272.     // Extract the list, count the list's elements, and then process each file in turn.
  273.     // Return any errors to the caller. 
  274.     //
  275.  
  276.     //
  277.     // Extract the list of aliases into fileListDesc
  278.     //
  279.     anError = AEGetParamDesc(aevt, keyDirectObject, typeAEList, &fileListDesc);
  280.  
  281.     //
  282.     // Make sure that's all we're supposed to do
  283.     //
  284.     if (!anError)
  285.         anError = GotRequiredAEParams(aevt);
  286.         
  287.     //
  288.     // Count the list elements
  289.     //
  290.  
  291.     if (!anError)
  292.         anError = AECountItems(&fileListDesc, &numFiles);
  293.  
  294.     //
  295.     // Get each file from the list and process it.  Even though the aevt
  296.     // contains a list of aliases, the AppleEvent Manager will convert
  297.     // each alias to an FSSpec if we ask it to.
  298.     //
  299.  
  300.     for (index = 1; (index <= numFiles) && !anError; index++)
  301.     {
  302.         //
  303.         // Pull the Nth file out of the aevt list
  304.         //
  305.  
  306.         anError = AEGetNthPtr( &fileListDesc, index, typeFSS, &actualKeyword,
  307.                             &actualType, (Ptr)&oneFSSpec, sizeof(oneFSSpec), &actualSize);
  308.  
  309.         if (!anError && !AppIsQuitting())
  310.         {
  311.             //
  312.             // Open or print the file
  313.             //
  314.  
  315.             anError = DoAEOpenFile(&oneFSSpec, index, numFiles, forPrinting);
  316.         }
  317.     } // for
  318.  
  319.     //
  320.     // All done with the list, throw it away
  321.     //
  322.  
  323.     AEDisposeDesc(&fileListDesc);
  324.  
  325.     return anError;
  326.  
  327. } // HandleAECommonOPDox()
  328.  
  329.  
  330.  
  331. // ---------------------------------------------------------------------
  332. #pragma segment Main
  333. static pascal OSErr HandleAEOdoc(    AEDescList        *aevt,
  334.                                     AEDescList        *reply,
  335.                                     long            refCon)
  336.     {
  337.     return HandleAECommonOPDox(aevt, reply, refCon, false/*forPrint*/);
  338.     } // HandleAEOdoc()
  339.  
  340.  
  341.  
  342. // ---------------------------------------------------------------------
  343. #pragma segment Main
  344. static pascal OSErr HandleAEPdoc(    AEDescList        *aevt,
  345.                                     AEDescList        *reply,
  346.                                     long            refCon)
  347.     {
  348.     return HandleAECommonOPDox(aevt, reply, refCon, true/*forPrint*/);
  349.     } // HandleAEPdoc()
  350.  
  351.  
  352. // ---------------------------------------------------------------------
  353. // AE Handler - Quit - Ask app to quit cleanly
  354. #pragma segment Main
  355. static pascal OSErr HandleAEQuit(AEDescList *aevt, AEDescList *reply, long refCon)
  356. {
  357. #pragma unused (reply,refCon)
  358.  
  359.     OSErr    anError;
  360.  
  361.     /* We don't normally expect any parms, but check in case the client requires any */
  362.     anError = GotRequiredAEParams(aevt);
  363.  
  364.     Stop_Flag = TRUE;
  365.     SetAppQuit();
  366.     return anError;
  367. } // HandleAEQuit
  368.  
  369.  
  370. // ---------------------------------------------------------------------
  371. // Handle any high level events (AppleEvents currently)
  372. void DoAEvts(EventRecord * theEventPtr)
  373. {
  374.     AEProcessAppleEvent(theEventPtr);
  375. } // DoAEvts
  376.  
  377.  
  378. // ---------------------------------------------------------------------
  379. // Handles All Core suite AppleEvents, dispatches them to appropriate
  380. // object dispatcher (Application, Translator, etc.)  This is done by
  381. // pre-extracting the class, and dispatching by class first, instead of
  382. // dispatching by AE command.  This allows us to group all events for
  383. // a class in a single file.  In other words, we dispatch by "app" or
  384. // "window" etc, instead of dispatching by "get data" or "close" etc.
  385. #pragma segment Main
  386.  
  387. static pascal OSErr CoreSuiteDispatcher(    AppleEvent    *aevt,
  388.                                             AppleEvent    *reply,
  389.                                             long        refCon)
  390.     {
  391.     OSErr            anError;
  392.     DescType        theTypeCode;
  393.     AEEventClass    theClassID;
  394.     AEEventID        theEventID;
  395.     Size            actualSize;
  396.     AEDesc            aeOspec        = {typeNull, NULL};
  397.     AEDesc            aeToken        = {typeNull, NULL};
  398.  
  399.     // extract the event class
  400.     anError = AEGetAttributePtr(aevt, keyEventClassAttr, typeType, &theTypeCode,
  401.                             (Ptr)&theClassID, sizeof(theClassID), &actualSize);
  402.     // extract the event ID
  403.     if (!anError)
  404.         anError = AEGetAttributePtr(aevt, keyEventIDAttr, typeType, &theTypeCode,
  405.                                 (Ptr)&theEventID, sizeof(theEventID), &actualSize);
  406.     // extract the direct parameter, the object specifier
  407.     if (!anError)
  408.         anError = AEGetKeyDesc(aevt, keyDirectObject, typeWildCard, &aeOspec);
  409.  
  410.     // go no further if errors
  411.     if (anError)
  412.         return anError;
  413.  
  414.     if (aeOspec.descriptorType == typeNull)
  415.         {
  416.         // null object (application), don't resolve it, no need to dispose it
  417.         aeToken = aeOspec;
  418.         theTypeCode = typeNull;
  419.         }
  420.     else
  421.         {
  422.         // resolve direct parm into a token
  423.         anError = AEResolve(&aeOspec, kAEIDoMinimum, &aeToken);
  424.         if (anError)
  425.             return anError;
  426.         theTypeCode = GetTokDescClass(aeToken); // get the dispatch class
  427.         }
  428.  
  429.     // handle the token class appropriately
  430.     switch (theTypeCode)
  431.         {
  432.         case typeNull:    // Application's token class
  433.             anError = AEAppDispatcher(theEventID, &aeToken, aevt, reply, refCon);
  434.             break;
  435. //        case cThing:
  436. //            anError = ThingDispatcher(theEventID, &aeToken, aevt, reply, refCon);
  437.             break;
  438.         default:
  439.             anError = errAEEventNotHandled;
  440.         }
  441.  
  442.     // all done with these puppies...
  443.     AEDisposeDesc(&aeOspec);
  444.     AEDisposeDesc(&aeToken);
  445.  
  446.     return anError;
  447.     } // CoreSuiteDispatcher
  448.  
  449.  
  450.  
  451. // ---------------------------------------------------------------------
  452. // Install our special accessor handler routines into the dispatch table
  453. static void InstallAESuiteHandlers(void)
  454.     {
  455.     OSErr    anError;
  456.  
  457.     //
  458.     // The Core aevts
  459.     //
  460.  
  461.     anError = AEInstallEventHandler(kAECoreSuite, typeWildCard,
  462.                         NewAEEventHandlerProc(CoreSuiteDispatcher), 0, false);
  463.  
  464.     //
  465.     // debug catch-all
  466.     //
  467.  
  468.     // debug, catch any unhandled events...
  469. /*
  470.     anError = AEInstallEventHandler(typeWildCard, typeWildCard,
  471.                         (AEEventHandlerUPP)HandleAllTheRest, 0, false);
  472. */
  473.  
  474.     // Install any callback functions
  475. /*
  476.     anError = AESetObjectCallbacks((compareProcPtr)NULL, 
  477.                     NewOSLCountProc(CountEmProc), 
  478.                     NewOSLDisposeTokenProc(DisposeTokenProc),
  479.                     (getMarkTokenProcPtr)NULL,
  480.                     (markProcPtr)NULL, 
  481.                     (adjustMarksProcPtr)NULL, 
  482.                     (getErrDescProcPtr)NULL);
  483. */
  484.     } // InstallAESuiteHandlers
  485.  
  486.  
  487. // ---------------------------------------------------------------------
  488. // Install our AppleEvent handlers (above) so they can be called automatically
  489. // by AEProcessAppleEvent()
  490. void InstallAppleEvents(void)
  491. {
  492.     OSErr    anError = noErr;
  493.     long    gestaltResult;
  494.  
  495.     //
  496.     // in case we're running an old AppleEvent System
  497.     //
  498.     anError = Gestalt(gestaltAppleEventsAttr, &gestaltResult);
  499.     if (anError == noErr)
  500.         {
  501.         if (!((gestaltResult>>gestaltAppleEventsPresent) & 1)) // no AEvts on system?
  502.             anError = -1; // need some Gestalt/AEvt error code, to be nice.
  503.         else // is OSL in MacOS?
  504.             if ((gestaltResult>>gestaltOSLInSystem) & 1)
  505.                 gAppleScriptAvail=TRUE;
  506. #if defined(powerc) || defined (__powerc)
  507.             else if ((ProcPtr)AEResolve != (ProcPtr)kUnresolvedCFragSymbolAddress)
  508. #endif
  509.                 // NOT built-in,   Then try to init the linked lib
  510.                 {
  511.                 anError = AEObjectInit();
  512.                 if (!anError)
  513.                     gAppleScriptAvail=TRUE;
  514.                 }
  515.         }
  516.  
  517.     //
  518.     // The REQUIRED aevts
  519.     //
  520.  
  521.     if (!anError)
  522.     anError = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
  523.                         NewAEEventHandlerProc(HandleAEOapp), 0, false);
  524.     if (!anError)
  525.     anError = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
  526.                         NewAEEventHandlerProc(HandleAEOdoc), 0, false);
  527.     if (!anError)
  528.     anError = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
  529.                         NewAEEventHandlerProc(HandleAEPdoc), 0, false);
  530.     if (!anError)
  531.     anError = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
  532.                         NewAEEventHandlerProc(HandleAEQuit), 0, false);
  533.  
  534.     //
  535.     // additional suites (Core, etc.) installed here
  536.     //
  537.     if (gAppleScriptAvail && !anError)
  538.         InstallAESuiteHandlers();
  539.  
  540. // if (anError) // DEBUG <>
  541. // (void)DisplayModalDialog(kdlog_GenericFatalErr, ok, 0,
  542. // "InstallAppleEvents: Cannot install AEvts", anError, ewcDoCentering, eMainDevice);
  543.  
  544. } // InstallAppleEvents
  545.  
  546.  
  547.  
  548.